package com.hyy.customer.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.hyy.api.domain.customer.CstmCustomer;
import com.hyy.api.domain.customer.bo.CstmCustomerBo;
import com.hyy.api.domain.customer.bo.CstmCustomerCmppConfigBo;
import com.hyy.api.domain.customer.bo.CstmCustomerHttpConfigBo;
import com.hyy.api.domain.customer.bo.CstmCustomerProviderChannelBo;
import com.hyy.api.domain.customer.redis.CstmCustomerCmppRedisDto;
import com.hyy.api.domain.customer.redis.CstmCustomerHttpRedisDto;
import com.hyy.api.domain.customer.vo.CstmCustomerCmppConfigVo;
import com.hyy.api.domain.customer.vo.CstmCustomerHttpConfigVo;
import com.hyy.api.domain.customer.vo.CstmCustomerProviderChannelVo;
import com.hyy.api.domain.customer.vo.CstmCustomerVo;
import com.hyy.api.domain.provider.bo.BindProviderChannelBo;
import com.hyy.api.domain.system.bo.SysUserBo;
import com.hyy.common.core.utils.MapstructUtils;
import com.hyy.common.core.utils.StringUtils;
import com.hyy.common.mybatis.core.page.TableDataInfo;
import com.hyy.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hyy.common.redis.utils.RedisUtils;
import com.hyy.customer.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.hyy.customer.mapper.CstmCustomerMapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.UUID;
import java.util.stream.Collectors;

import static com.hyy.api.constant.BusinessRedisConstants.*;

/**
 * 下游客户Service业务层处理
 *
 * @author ruoyi
 * @date 2025-05-16
 */
@RequiredArgsConstructor
@Service
public class CstmCustomerServiceImpl implements ICstmCustomerService {

    private final CstmCustomerMapper baseMapper;

    private final IModCstmSysUserService sysUserService;

    private final ICstmCustomerCmppConfigService cmppConfigService;

    private final ICstmCustomerHttpConfigService httpConfigService;
    private final ICstmCustomerProviderChannelService customerProviderChannelService;

    /**
     * 查询下游客户
     *
     * @param id 主键
     * @return 下游客户
     */
    @Override
    public CstmCustomerVo queryById(Long id){
        CstmCustomerVo cstmCustomerVo = baseMapper.selectVoById(id);
        String method = cstmCustomerVo.getMethod();
        JSONObject methodParams = new JSONObject();
        JSONObject cmpp = new JSONObject();
        cmpp.put("spCode","");
        cmpp.put("connections","");
        cmpp.put("acceptRate","");
        cmpp.put("needProviderDest",1);
        JSONObject http = new JSONObject();
        http.put("acceptRate","");

        if("cmpp".equals(method)){
            CstmCustomerCmppConfigVo cstmCustomerCmppConfigVo = cmppConfigService.queryByCustomerId(id);
            cmpp.put("spCode",cstmCustomerCmppConfigVo.getSpCode());
            cmpp.put("connections",cstmCustomerCmppConfigVo.getConnections());
            cmpp.put("acceptRate",cstmCustomerCmppConfigVo.getAcceptRate());
            cmpp.put("needProviderDest",cstmCustomerCmppConfigVo.getNeedProviderDest());
        }
        if("http".equals(method)){
            CstmCustomerHttpConfigVo cstmCustomerHttpConfigVo = httpConfigService.queryByCustomerId(id);
            http.put("acceptRate",cstmCustomerHttpConfigVo.getAcceptRate());
        }

        methodParams.put("cmpp",cmpp);
        methodParams.put("http",http);
        cstmCustomerVo.setMethodParams(methodParams.toJSONString());
        return cstmCustomerVo;
    }

    /**
     * 分页查询下游客户列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 下游客户分页列表
     */
    @Override
    public TableDataInfo<CstmCustomerVo> queryPageList(CstmCustomerBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<CstmCustomer> lqw = buildQueryWrapper(bo);
        Page<CstmCustomerVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的下游客户列表
     *
     * @param bo 查询条件
     * @return 下游客户列表
     */
    @Override
    public List<CstmCustomerVo> queryList(CstmCustomerBo bo) {
        LambdaQueryWrapper<CstmCustomer> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<CstmCustomer> buildQueryWrapper(CstmCustomerBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<CstmCustomer> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(CstmCustomer::getId);
        lqw.like(StringUtils.isNotBlank(bo.getName()), CstmCustomer::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), CstmCustomer::getCode, bo.getCode());
        lqw.eq(bo.getStatus() != null, CstmCustomer::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getMethod()), CstmCustomer::getMethod, bo.getMethod());
        lqw.eq(bo.getCorporateId() != null, CstmCustomer::getCorporateId, bo.getCorporateId());
        lqw.eq(bo.getPrice() != null, CstmCustomer::getPrice, bo.getPrice());
        return lqw;
    }

    /**
     * 新增下游客户
     *
     * @param bo 下游客户
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(CstmCustomerBo bo) {
        String methodParams = bo.getMethodParams();

        CstmCustomer add = MapstructUtils.convert(bo, CstmCustomer.class);
        validEntityBeforeSave(add);

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            String method = add.getMethod();
            if("cmpp".equals(method)){
                //新增cmpp参数表
                CstmCustomerCmppConfigBo cmppConfigBo =  JSON.parseObject(methodParams, CstmCustomerCmppConfigBo.class);
                cmppConfigBo.setCustomerId(add.getId());
                cmppConfigService.insertByBo(cmppConfigBo);
                //cmpp参数插入到缓存中
                cmppConfigToRedis(add.getId());
            }
            if("http".equals(method)){
                //新增http参数表
                CstmCustomerHttpConfigBo httpConfigBo =  JSON.parseObject(methodParams, CstmCustomerHttpConfigBo.class);
                httpConfigBo.setCustomerId(add.getId());
                httpConfigService.insertByBo(httpConfigBo);
                //http参数插入到缓存中
                httpConfigToRedis(add.getId());
            }

            //新增sys_user表
            SysUserBo sysUserBo = new SysUserBo();
            sysUserBo.setUserName(bo.getCode());
            sysUserBo.setPassword(bo.getPwd());
            sysUserBo.setNickName(bo.getName());
            sysUserBo.setStatus("0");
            sysUserService.insertCustomerUser(sysUserBo);
        }
        return flag;
    }

    private void httpConfigToRedis(Long id) {

        //用户表信息
        CstmCustomerVo cstmCustomerVo = queryById(id);
        //http参数表信息
        CstmCustomerHttpConfigVo httpConfigVo = httpConfigService.queryByCustomerId(id);
        if(httpConfigVo == null){
            return;
        }
        CstmCustomerHttpRedisDto cstmCustomerHttpRedisDto = new CstmCustomerHttpRedisDto();
        //用户信息
        cstmCustomerHttpRedisDto.setCustomerId(cstmCustomerVo.getId());
        cstmCustomerHttpRedisDto.setCode(cstmCustomerVo.getCode());
        cstmCustomerHttpRedisDto.setPwd(cstmCustomerVo.getPwd());
        cstmCustomerHttpRedisDto.setBindIps(cstmCustomerVo.getIps());
        cstmCustomerHttpRedisDto.setStatus(cstmCustomerVo.getStatus());
        //参数信息
        cstmCustomerHttpRedisDto.setAcceptRate(httpConfigVo.getAcceptRate());

        //写入缓存
        String redisKey = String.format(CSTM_CUSTOMER_HTTP_CACHE, cstmCustomerVo.getCode());
        RedisUtils.setCacheObject(redisKey, cstmCustomerHttpRedisDto);
    }

    private void cmppConfigToRedis(Long id) {
        //用户表信息
        CstmCustomerVo cstmCustomerVo = queryById(id);
        //cmpp参数表信息
        CstmCustomerCmppConfigVo cmppConfigVo = cmppConfigService.queryByCustomerId(id);
        if(cmppConfigVo == null){
            return;
        }
        CstmCustomerCmppRedisDto cstmCustomerCmppRedisDto = new CstmCustomerCmppRedisDto();
        //用户信息
        cstmCustomerCmppRedisDto.setCustomerId(cstmCustomerVo.getId());
        cstmCustomerCmppRedisDto.setCode(cstmCustomerVo.getCode());
        cstmCustomerCmppRedisDto.setPwd(cstmCustomerVo.getPwd());
        cstmCustomerCmppRedisDto.setBindIps(cstmCustomerVo.getIps());
        cstmCustomerCmppRedisDto.setStatus(cstmCustomerVo.getStatus());
        //参数信息
        cstmCustomerCmppRedisDto.setAcceptRate(cmppConfigVo.getAcceptRate());
        cstmCustomerCmppRedisDto.setSpCode(cmppConfigVo.getSpCode());
        cstmCustomerCmppRedisDto.setNeedProviderDest(cmppConfigVo.getNeedProviderDest());
        cstmCustomerCmppRedisDto.setConnections(cmppConfigVo.getConnections());
        //写入缓存
        String redisKey = String.format(CSTM_CUSTOMER_CMPP_CACHE, cstmCustomerVo.getCode());
        RedisUtils.setCacheObject(redisKey, cstmCustomerCmppRedisDto);

    }

    /**
     * 修改下游客户
     *
     * @param bo 下游客户
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(CstmCustomerBo bo) {
        CstmCustomer update = MapstructUtils.convert(bo, CstmCustomer.class);
        String methodParams = bo.getMethodParams();
        validEntityBeforeSave(update);
        boolean flag = baseMapper.updateById(update) > 0;

        if (flag) {
            Long cusId = update.getId();
            bo.setId(update.getId());
            String method = update.getMethod();
            if("cmpp".equals(method)){
                //新增cmpp参数表
                CstmCustomerCmppConfigBo cmppConfigBo =  JSON.parseObject(methodParams, CstmCustomerCmppConfigBo.class);
                cmppConfigService.updateByCustomerId(cusId,cmppConfigBo);
                //cmpp参数插入到缓存中
                cmppConfigToRedis(cusId);
            }
            if("http".equals(method)){
                //新增http参数表
                CstmCustomerHttpConfigBo httpConfigBo =  JSON.parseObject(methodParams, CstmCustomerHttpConfigBo.class);
                httpConfigService.updateByCustomerId(cusId,httpConfigBo);
                //http参数插入到缓存中
                httpConfigToRedis(cusId);
            }

        }
        return flag;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(CstmCustomer entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除下游客户信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    @Transactional
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        //获取客户的code集合
        List<CstmCustomerVo> cstmCustomerVos = baseMapper.selectVoByIds(ids);
        if(CollUtil.isEmpty(cstmCustomerVos)){
            return false;
        }
        //组装一个id=>CstmCustomerVo的map
        Map<Long, CstmCustomerVo> customerVoMap = cstmCustomerVos.stream().collect(Collectors.toMap(CstmCustomerVo::getId, i->i));

        boolean flag = baseMapper.deleteByIds(ids) > 0;
        if(flag){

            for (Long id : ids) {
                CstmCustomerVo cstmCustomerVo = customerVoMap.get(id);
                String code = cstmCustomerVo.getCode();

                //删除sys_user表
                sysUserService.deleteByCode(code);
                String method = cstmCustomerVo.getMethod();
                if("cmpp".equals(method)){
                    //删除cmpp参数表
                    cmppConfigService.deleteByCustomerId(id);
                    //cmpp参数从缓存中删除
                    String redisKey = String.format(CSTM_CUSTOMER_CMPP_CACHE, code);
                    RedisUtils.deleteObject(redisKey);
                }
                if("http".equals(method)){
                    //删除http参数表
                    httpConfigService.deleteByCustomerId(id);
                    //http参数从缓存中删除
                    String redisKey = String.format(CSTM_CUSTOMER_HTTP_CACHE, code);
                    RedisUtils.deleteObject(redisKey);
                }

                //删除通道表
                customerProviderChannelService.deleteByCustomerId(id);
            }

        }


        return flag;
    }

    @Override
    public CstmCustomerVo newCustomer() {
        Integer cstm_corporate_start = RedisUtils.getCacheObject(CSTM_CUSTOMER_START);
        if(cstm_corporate_start == null){
            RedisUtils.setCacheObject(CSTM_CUSTOMER_START, 200000);
        }


        long account = RedisUtils.incrAtomicValue(CSTM_CUSTOMER_START);
        CstmCustomerVo cstmCustomerVo = new CstmCustomerVo();
        cstmCustomerVo.setCode(account+"");
        String key = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
        cstmCustomerVo.setPwd(key);
        cstmCustomerVo.setStatus(1);

        return cstmCustomerVo;
    }

    @Override
    public boolean bindProviderChannel(BindProviderChannelBo bo) {
        List<CstmCustomerProviderChannelBo> boList = bo.getBoList();
        Long customerId = bo.getCustomerId();

        if(customerId==null || CollUtil.isEmpty(boList)){
            return false;
        }
        //删除原始的通道
        customerProviderChannelService.deleteByCustomerId(customerId);

        for (CstmCustomerProviderChannelBo cstmCustomerProviderChannelBo : boList) {
            cstmCustomerProviderChannelBo.setCustomerId(customerId);
        }
        //批量插入通道
        return customerProviderChannelService.saveBatch(boList);
    }

    @Override
    public List<CstmCustomerProviderChannelVo> getProviderChannel(Long customerId) {
        return  customerProviderChannelService.selectByCustomerId(customerId);
    }
}
